package puzzle.slilin2.solver;

import puzzle.common.data.HatanException;
import puzzle.common.point.Pnt;
import puzzle.slilin2.data.CellType;
import puzzle.slilin2.data.LineCellState;
import puzzle.slilin2.data.SlilinPntHelper;
import puzzle.slilin2.data.SlilinBoard;

class DotRule extends SlilinCellRule {

	@Override
	protected CellType appliedCellType() {
		return CellType.DOT;
	}

	@Override
	protected boolean skipOutside() {
		return false;
	}
	
	@Override
	protected boolean skipUnmodifiedCell() {
		return true;
	}

	public boolean apply(SlilinBoard b, Pnt p0) throws HatanException {
		LineCount lc = new LineCount(b, SlilinPntHelper.getLinePointsAroundDot(b, p0));

		// 点の周辺の線の状態がすべて決まっていれば何もしない
		if (lc.getUnfixedCellStates().size() == 0) return false;

		boolean isChanged = false;

		if (lc.getForbiddenCount() == 3 || lc.getExistsCount() == 2) {
			if (lc.getUnfixedCellStates().isEmpty()) {
				throw new HatanException();
			}

			// これ以上この点に線は入ってこない
			isChanged = true;
			for (LineCellState s : lc.getUnfixedCellStates()) {
				s.setForbidden(true);
			}
		} else if (lc.getForbiddenCount() == 2 && lc.getExistsCount() == 1) {
			// 一本線が入ってきている状態で、残り候補がひとつなので、そこに線をつなげる
			isChanged = true;
			for (LineCellState s : lc.getUnfixedCellStates()) {
				s.setExists(true);
			}
		} else if (lc.getExistsCount() > 2) {
			// 3本以上線が入っていたらおかしい
			throw new HatanException();
		}
		
		return isChanged;

	}

}
